import json
import os
import time
from datetime import datetime

DATA_FILE = "mail_data.txt"

products = []
orders = []
users = []
logs = []
backup_files = []


# 商品类
class Product:
    def __init__(self, pid, name, category, price, stock):
        self.pid = pid
        self.name = name
        self.category = category
        self.price = price
        self.stock = stock

    def to_dict(self):
        return {
            "pid": self.pid,
            "name": self.name,
            "category": self.category,
            "price": self.price,
            "stock": self.stock
        }

    @staticmethod
    def from_dict(data):
        return Product(data["pid"], data["name"], data["category"], data["price"], data["stock"])

    def to_csv(self):
        return f"{self.pid},{self.name},{self.category},{self.price},{self.stock}"

    @staticmethod
    def from_csv(line):
        parts = line.strip().split(',')
        return Product(parts[0], parts[1], parts[2], float(parts[3]), int(parts[4]))


# 订单类
class Order:
    def __init__(self, oid, phone, pid, quantity, total, order_time=None):
        self.oid = oid
        self.phone = phone
        self.pid = pid
        self.quantity = quantity
        self.total = total
        self.order_time = order_time or datetime.now().strftime("%Y-%m-%d %H:%M:%S")

    def to_dict(self):
        return {
            "oid": self.oid,
            "phone": self.phone,
            "pid": self.pid,
            "quantity": self.quantity,
            "total": self.total,
            "order_time": self.order_time
        }

    @staticmethod
    def from_dict(data):
        return Order(data["oid"], data["phone"], data["pid"], data["quantity"], data["total"], data["order_time"])

    def to_csv(self):
        return f"{self.oid},{self.phone},{self.pid},{self.quantity},{self.total},{self.order_time}"

    @staticmethod
    def from_csv(line):
        parts = line.strip().split(',')
        return Order(parts[0], parts[1], parts[2], int(parts[3]), float(parts[4]), parts[5])


# 用户类（管理员）
class User:
    def __init__(self, username, password, role="normal"):
        self.username = username
        self.password = password
        self.role = role
        self.login_attempts = 0
        self.locked_until = 0

    def to_dict(self):
        return {
            "username": self.username,
            "password": self.password,
            "role": self.role,
            "login_attempts": self.login_attempts,
            "locked_until": self.locked_until
        }

    @staticmethod
    def from_dict(data):
        user = User(data["username"], data["password"], data["role"])
        user.login_attempts = data.get("login_attempts", 0)
        user.locked_until = data.get("locked_until", 0)
        return user

    def to_csv(self):
        return f"{self.username},{self.password},{self.role},{self.login_attempts},{self.locked_until}"

    @staticmethod
    def from_csv(line):
        parts = line.strip().split(',')
        user = User(parts[0], parts[1], parts[2])
        user.login_attempts = int(parts[3])
        user.locked_until = float(parts[4])
        return user


# 系统日志类
class Systemlog:
    def __init__(self, action, user, timestamp=None, details=""):
        self.action = action
        self.user = user
        self.timestamp = timestamp or datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        self.details = details

    def to_dict(self):
        return {
            "action": self.action,
            "user": self.user,
            "timestamp": self.timestamp,
            "details": self.details
        }

    @staticmethod
    def from_dict(data):
        return Systemlog(data["action"], data["user"], data["timestamp"], data.get("details", ""))

    def to_csv(self):
        # 处理details中可能包含逗号的情况
        safe_details = self.details.replace(',', ';')
        return f"{self.action},{self.user},{self.timestamp},{safe_details}"

    @staticmethod
    def from_csv(line):
        parts = line.strip().split(',')
        details = parts[3].replace(';', ',') if len(parts) > 3 else ""
        return Systemlog(parts[0], parts[1], parts[2], details)


# 数据持久化
def load_data():
    global products, orders, users, logs, backup_files
    if os.path.exists(DATA_FILE):
        try:
            with open(DATA_FILE, 'r', encoding='utf-8') as f:
                lines = f.readlines()

            current_section = None
            products.clear()
            orders.clear()
            users.clear()
            logs.clear()
            backup_files.clear()

            for line in lines:
                line = line.strip()
                if not line or line.startswith('#'):
                    # 检查是否是段落的注释标题
                    if "商品数据格式" in line:
                        current_section = "products"
                    elif "订单数据格式" in line:
                        current_section = "orders"
                    elif "用户数据格式" in line:
                        current_section = "users"
                    elif "日志数据格式" in line:
                        current_section = "logs"
                    elif "备份文件" in line:
                        current_section = "backup_files"
                    continue

                if current_section == "products":
                    products.append(Product.from_csv(line))
                elif current_section == "orders":
                    orders.append(Order.from_csv(line))
                elif current_section == "users":
                    users.append(User.from_csv(line))
                elif current_section == "logs":
                    logs.append(Systemlog.from_csv(line))
                elif current_section == "backup_files":
                    backup_files.append(line)

            # 如果没有admin用户，创建默认管理员
            if not any(u.username == "admin" for u in users):
                users.append(User("admin", "Admin123", "super"))

        except Exception as e:
            print(f"加载数据失败：{e}")
            initialize_default_data()
    else:
        initialize_default_data()


def save_data():
    try:
        with open(DATA_FILE, 'w', encoding='utf-8') as f:
            # 保存商品数据
            f.write("# 商品数据格式: pid,name,category,price,stock\n")
            for product in products:
                f.write(product.to_csv() + '\n')
            f.write('\n')

            # 保存订单数据
            f.write("# 订单数据格式: oid,phone,pid,quantity,total,order_time\n")
            for order in orders:
                f.write(order.to_csv() + '\n')
            f.write('\n')

            # 保存用户数据
            f.write("# 用户数据格式: username,password,role,login_attempts,locked_until\n")
            for user in users:
                f.write(user.to_csv() + '\n')
            f.write('\n')

            # 保存日志数据
            f.write("# 日志数据格式: action,user,timestamp,details\n")
            for log in logs[-100:]:  # 只保存最近100条日志
                f.write(log.to_csv() + '\n')
            f.write('\n')

            # 保存备份文件列表
            if backup_files:
                f.write("# 备份文件列表\n")
                for backup_file in backup_files:
                    f.write(backup_file + '\n')

    except Exception as e:
        print(f"保存数据失败：{e}")


def initialize_default_data():
    global users
    users = [User("admin", "Admin123", "super")]
    save_data()


# 用户认证
def authenticate_user():
    print("\n=== 用户登录 ===")
    while True:
        username = input("请输入用户名：").strip()
        password = input("请输入密码：").strip()

        user = next((u for u in users if u.username == username), None)
        if not user:
            print("用户名不存在！")
            continue

        # 检查账户是否被锁定
        if user.locked_until > time.time():
            remaining = int(user.locked_until - time.time())
            print(f"账户已被锁定，请{remaining}秒后再试")
            continue

        if user.password == password:
            user.login_attempts = 0
            save_data()
            log_action("login", username, "登录成功")
            print("登录成功！")
            return user
        else:
            user.login_attempts += 1
            if user.login_attempts >= 3:
                user.locked_until = time.time() + 30
                print("连续3次密码错误，账户已锁定30秒")
            else:
                print(f"密码错误，还剩{3 - user.login_attempts}次尝试机会")
            save_data()


# 日志记录
def log_action(action, user, details=""):
    log = Systemlog(action, user, details=details)
    logs.append(log)
    if len(logs) > 1000:
        logs.pop(0)


# 商品管理功能
def add_product(user):
    print("\n=== 添加商品 ===")
    while True:
        pid = input("请输入商品编号：").strip()
        if any(p.pid == pid for p in products):
            print("商品编号已存在，请重新输入")
            continue
        name = input("请输入商品名称：").strip()
        category = input("请输入商品分类：").strip()

        try:
            price = float(input("请输入商品单价："))
            if price <= 0:
                print("单价必须大于0")
                continue
        except ValueError:
            print("单价必须是数字")
            continue

        try:
            stock = int(input("请输入库存数量："))
            if stock <= 0:
                print("库存数量必须大于0")
                continue
        except ValueError:
            print("库存数量必须是整数")
            continue

        product = Product(pid, name, category, price, stock)
        products.append(product)
        save_data()
        log_action("add_product", user.username, f"添加商品：{name}({pid})")
        print("添加成功！")
        break


def view_products():
    print("\n=== 所有商品 ===")
    if not products:
        print("系统中暂无商品信息")
        return

    print("编号\t名称\t分类\t单价\t库存\t总价值")
    print("-" * 50)
    for p in products:
        total_value = p.price * p.stock
        print(f"{p.pid}\t{p.name}\t{p.category}\t{p.price:.2f}\t{p.stock}\t{total_value:.2f}")


def delete_product(user):
    print("\n=== 删除商品 ===")
    pid = input("请输入要删除的商品编号：").strip()
    product = next((p for p in products if p.pid == pid), None)
    if not product:
        print("商品不存在")
        return
    products.remove(product)
    save_data()
    log_action("delete_product", user.username, f"删除商品：{product.name}({pid})")
    print("删除成功")


def modify_product(user):
    print("\n=== 修改商品 ===")
    pid = input("请输入要修改的商品编号：").strip()
    product = next((p for p in products if p.pid == pid), None)
    if not product:
        print("商品不存在")
        return
    print(f"当前商品信息：{product.name}, 分类：{product.category}, 单价：{product.price:.2f}, 库存：{product.stock}")
    while True:
        print("\n请选择要修改的项目:")
        print("1. 商品名称")
        print("2. 商品分类")
        print("3. 单价")
        print("4. 库存数量")
        print("5. 无修改，返回上一级")

        choice = input("请选择(1-5): ").strip()
        if choice == "1":
            new_name = input("请输入新的商品名称：").strip()
            product.name = new_name
            print("商品名称修改成功")
        elif choice == "2":
            new_category = input("请输入新的商品分类：").strip()
            product.category = new_category
            print("商品分类修改成功")
        elif choice == "3":
            try:
                new_price = float(input("请输入新的单价："))
                if new_price <= 0:
                    print("单价必须大于0")
                    continue
                product.price = new_price
                print("单价修改成功")
            except ValueError:
                print("单价必须是数字")
        elif choice == "4":
            try:
                new_stock = int(input("请输入新的库存数量："))
                if new_stock < 0:
                    print("库存数量不能为负数")
                    continue
                product.stock = new_stock
                print("库存数量修改成功")
            except ValueError:
                print("库存数量必须是整数")
        elif choice == "5":
            break
        else:
            print("无效选择")
        save_data()
        log_action("modify_product", user.username, f"修改商品：{product.name}({pid})")


# 订单管理功能
def create_order(user):
    print("\n=== 创建订单 ===")
    oid = input("请输入订单编号：").strip()
    if any(o.oid == oid for o in orders):
        print("订单编号已存在")
        return
    phone = input("请输入用户手机号：").strip()
    if not (phone.isdigit() and len(phone) == 11):
        print("手机号必须是11位数字")
        return
    pid = input("请输入商品编号：").strip()
    product = next((p for p in products if p.pid == pid), None)
    if not product:
        print("商品不存在")
        return
    try:
        quantity = int(input("请输入购买数量："))
        if quantity <= 0:
            print("购买数量必须大于0")
            return
    except ValueError:
        print("购买数量必须是整数")
        return
    if product.stock < quantity:
        print("库存不足")
        return

    try:
        product.stock -= quantity
        total = product.price * quantity
        order = Order(oid, phone, pid, quantity, total)
        orders.append(order)
        save_data()
        log_action("create_order", user.username, f"创建订单: {oid}")
        print("订单创建成功!")
    except Exception as e:
        product.stock += quantity
        print(f"订单创建失败: {e}")


def query_order():
    print("\n=== 查询订单 ===")
    oid = input("请输入订单编号：").strip()
    order = next((o for o in orders if o.oid == oid), None)
    if not order:
        print("订单不存在")
        return
    product = next((p for p in products if p.pid == order.pid), None)
    product_name = product.name if product else "未知商品"

    print(f"订单编号: {order.oid}")
    print(f"用户手机: {order.phone}")
    print(f"商品信息: {product_name}({order.pid})")
    print(f"购买数量: {order.quantity}")
    print(f"总金额: {order.total:.2f}")
    print(f"下单时间: {order.order_time}")


def cancel_order(user):
    print("\n=== 撤销订单 ===")
    oid = input("请输入要撤销的订单编号: ").strip()
    order = next((o for o in orders if o.oid == oid), None)

    if not order:
        print("订单不存在")
        return

    product = next((p for p in products if p.pid == order.pid), None)
    if product:
        product.stock += order.quantity

    orders.remove(order)
    save_data()
    log_action("cancel_order", user.username, f"撤销订单: {oid}")
    print("订单撤销成功，库存已恢复!")


def order_statistics():
    print("\n=== 订单统计分析 ===")
    if not orders:
        print("暂无订单数据")
        return

    category_stats = {}
    for order in orders:
        product = next((p for p in products if p.pid == order.pid), None)
        if product:
            category = product.category
            if category not in category_stats:
                category_stats[category] = {"quantity": 0, "total": 0}
            category_stats[category]["quantity"] += order.quantity
            category_stats[category]["total"] += order.total

    print("分类\t销售数量\t销售总额")
    print("-" * 30)
    for category, stats in category_stats.items():
        print(f"{category}\t{stats['quantity']}\t\t{stats['total']:.2f}")


def backup_data(user):
    print("\n=== 数据备份 ===")
    backup_file = f"backup_{datetime.now().strftime('%Y%m%d_%H%M%S')}.txt"

    try:
        with open(backup_file, 'w', encoding='utf-8') as f:
            # 备份商品数据
            f.write("# 商品数据格式: pid,name,category,price,stock\n")
            for product in products:
                f.write(product.to_csv() + '\n')
            f.write('\n')

            # 备份订单数据
            f.write("# 订单数据格式: oid,phone,pid,quantity,total,order_time\n")
            for order in orders:
                f.write(order.to_csv() + '\n')
            f.write('\n')

            # 备份用户数据
            f.write("# 用户数据格式: username,password,role,login_attempts,locked_until\n")
            for user_obj in users:
                f.write(user_obj.to_csv() + '\n')
            f.write('\n')

            # 备份日志数据
            f.write("# 日志数据格式: action,user,timestamp,details\n")
            for log in logs:
                f.write(log.to_csv() + '\n')

        backup_files.append(backup_file)
        save_data()
        log_action("backup_data", user.username, f"备份到文件：{backup_file}")
        print(f"数据已备份到 {backup_file}")
    except Exception as e:
        print(f"备份失败：{e}")


def restore_data(user):
    print("\n=== 数据恢复 ===")
    if not backup_files:
        print("暂无备份文件")
        return
    print("可用的备份文件：")
    for i, file in enumerate(backup_files, 1):
        print(f"{i}. {file}")
    try:
        choice = int(input("请选择要恢复的备份文件编号："))
        if 1 <= choice <= len(backup_files):
            selected_file = backup_files[choice - 1]
            if not os.path.exists(selected_file):
                print("备份文件不存在")
                return

            # 读取备份文件
            with open(selected_file, 'r', encoding='utf-8') as f:
                lines = f.readlines()

            products_backup = []
            orders_backup = []
            users_backup = []
            logs_backup = []

            current_section = None
            for line in lines:
                line = line.strip()
                if not line or line.startswith('#'):
                    if "商品数据格式" in line:
                        current_section = "products"
                    elif "订单数据格式" in line:
                        current_section = "orders"
                    elif "用户数据格式" in line:
                        current_section = "users"
                    elif "日志数据格式" in line:
                        current_section = "logs"
                    continue

                if current_section == "products":
                    products_backup.append(Product.from_csv(line))
                elif current_section == "orders":
                    orders_backup.append(Order.from_csv(line))
                elif current_section == "users":
                    users_backup.append(User.from_csv(line))
                elif current_section == "logs":
                    logs_backup.append(Systemlog.from_csv(line))

            global products, orders, users, logs
            products = products_backup
            orders = orders_backup
            users = users_backup
            logs = logs_backup

            save_data()
            log_action("restore_data", user.username, f"从文件恢复: {selected_file}")
            print("数据恢复成功!")
        else:
            print("无效的选择")
    except (ValueError, IndexError):
        print("输入错误")


def view_logs():
    print("\n=== 系统日志 ===")
    if not logs:
        print("暂无日志记录")
        return

    print("时间\t\t用户\t操作\t详情")
    print("-" * 50)
    for log in logs[-20:]:
        print(f"{log.timestamp}\t{log.user}\t{log.action}\t{log.details}")


def clear_logs(user):
    global logs
    logs = []
    save_data()
    log_action("clear_logs", user.username, "清空所有日志")
    print("日志已清空")


def main_menu(user):
    while True:
        print("\n=== 在线商城订单管理系统 ===")
        print(f"当前用户: {user.username} ({user.role}管理员)")
        print("1. 添加商品信息")
        print("2. 查看所有商品")

        if user.role == "super":
            print("3. 删除商品信息")
            print("4. 修改商品信息")

        print("5. 创建用户订单")
        print("6. 查询订单信息")
        print("7. 撤销订单")
        print("8. 订单统计分析")

        if user.role == "super":
            print("9. 数据备份")
            print("10. 数据恢复")
            print("11. 查看系统日志")
            print("12. 清空系统日志")
            print("13. 退出系统")
        else:
            print("9. 退出系统")

        choice = input("请选择操作: ").strip()

        if choice == "1":
            add_product(user)
        elif choice == "2":
            view_products()
        elif choice == "3" and user.role == "super":
            delete_product(user)
        elif choice == "4" and user.role == "super":
            modify_product(user)
        elif choice == "5":
            create_order(user)
        elif choice == "6":
            query_order()
        elif choice == "7":
            cancel_order(user)
        elif choice == "8":
            order_statistics()
        elif choice == "9" and user.role == "super":
            backup_data(user)
        elif choice == "10" and user.role == "super":
            restore_data(user)
        elif choice == "11" and user.role == "super":
            view_logs()
        elif choice == "12" and user.role == "super":
            clear_logs(user)
        elif (choice == "13" and user.role == "super") or (choice == "9" and user.role != "super"):
            log_action("logout", user.username, "退出系统")
            print("感谢使用，再见!")
            break
        else:
            print("无效选择或权限不足")


def main():
    print("=== 在线商城订单管理系统 ===")
    load_data()

    user = authenticate_user()
    main_menu(user)


if __name__ == "__main__":
    main()